<template>
  <div>
    <transition name="audio-player">
      <div class="audio_player-block" v-if="playerShow" />
    </transition>
    <div :class="['player-bg', {close:!playerShow}]">
      <div class="player-wrapper">
        <div @click="playerShow=!playerShow" class="audio_player_show-btn">
          <div class="item-t-s el-icon-caret-top" v-if="playerShow" />
          <div class="item-t-s el-icon-caret-bottom" v-else />
        </div>
        <div class="wrapper-controller">
          <div @click="$store.commit('audio/PLAY_PREV')" class="item-t-s item-controller-btn item-prev iconfont icon-ziyuanldpi8" />
          <div :class="['item-t-s item-controller-btn item-play iconfont', audioStatus?'icon-zanting':'icon-ziyuanldpi11']" @click="$store.commit('audio/TOOGEL_AUDIO_STATUS')" />
          <div @click="$store.commit('audio/PLAY_NEXT')" class="item-t-s item-controller-btn item-next iconfont icon-ziyuanldpi9" />
        </div>

        <div class="wrapper-middle">
          <el-image :src="nowPlay.cover" class="item-audio-cover" fit="cover" />
          <div class="wrapper-audio">
            <div class="item-audio-info">
              <div class="item-t-s audio-name">
                <span :class="['span-pc',{active: nowPlay.name.length > 90}]" v-html="nowPlay.name" />
                <span :class="['span-mb',{active: nowPlay.name.length > 30}]" style="display:none" v-html="nowPlay.name" />
              </div>
              <div class="item-t-s audio-artist">
                <span :class="['span-pc',{active:nowPlay.name.length + nowPlay.artist.length > 102}]" v-html="nowPlay.artist" />
                <span :class="['span-mb',{active:nowPlay.artist.length > 8}]" style="display:none" v-html="nowPlay.artist" />
              </div>
            </div>
            <div class="progress-wrapper">
              <div class="item-progress" ref="progress">
                <div :style="`width:${dragging?newPosition:activeLength}%`" class="item-progress-played" />
                <div :style="`width:${buffered}%`" class="item-progress-loaded" />
                <div :style="`left:${dragging?newPosition:activeLength}%`" @mousedown="onButtonDown" @touchstart="onButtonDown" class="item-progress-btn" />
              </div>
            </div>
          </div>
          <div class="wrapper-timer">
            <div>{{nowPlay.current}}</div>
            <span>/</span>
            <div>{{nowPlay.durationFromat}}</div>
          </div>
        </div>

        <div class="wrapper-controller-other">
          <div :class="['item-t-s item-loop iconfont','icon-ziyuanldpi2']" />
          <div :class="['item-t-s item-volume iconfont', comVolume]" @click="volumeController = !volumeController">
            <mvSlider :value="Math.floor(audioVolume*100)" @input="volumeHandler" class="volume-controller" v-if="volumeController" />
          </div>
          <div :class="loopModel | loopModelFormat" @click="$store.commit('audio/TOOGEL_LOOP_MODEL')" class="item-t-s item-loop iconfont" />
          <div :class="['item-t-s item-list iconfont', 'icon-ziyuanldpi4']" @click="$store.commit('audio/TOOGEL_PLAYLIST_STATE')">
            <span>{{playList.length}}</span>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { mapGetters } from 'vuex';
import mvSlider from './slider/main.vue';

export default {
    filters: {
        loopModelFormat(loopModel) {
            const obj = {
                0: 'icon-danquxunhuan1',
                1: 'icon-ziyuanldpi14',
                2: 'icon-ziyuanldpi10',
            };
            return obj[loopModel];
        },
    },
    components: { mvSlider },
    data() {
        return {
            playerShow: false,
            volumeController: false,
            progessStart: 0,
            progressWidth: 0,
            startX: 0,
            moveX: 0,
            newPosition: 0,
            dragging: false,
            isClick: false,
        };
    },
    computed: {
        ...mapGetters([
            'audio',
            'audioStatus',
            'audioVolume',
            'loopModel',
            'activeLength',
            'buffered',
            'audioListState',
            'playList',
            'nowPlay',
        ]),
        comVolume() {
            const { audioVolume } = this;
            if (audioVolume === 0) {
                return 'icon-ziyuanldpi3';
            }
            return audioVolume < 0.5 ? 'icon-ziyuanldpi12' : 'icon-ziyuanldpi13';
        },
    },
    watch: {
        audioStatus(val) {
            if (val) this.playerShow = true;
        },
    },
    methods: {
        volumeHandler(data) {
            this.$store.commit('audio/SETTING_VOLUME', data);
        },
        getProgressStyle() {
            this.progressWidth = this.$refs.progress.offsetWidth;
            this.progressStart = this.$refs.progress.getBoundingClientRect().left;
        },
        onButtonDown(event) {
            event.preventDefault();
            this.getProgressStyle();
            this.onDragStart(event);
            window.addEventListener('mousemove', this.onDragging);
            window.addEventListener('touchmove', this.onDragging);
            window.addEventListener('mouseup', this.onDragEnd);
            window.addEventListener('touchend', this.onDragEnd);
            window.addEventListener('contextmenu', this.onDragEnd);
        },
        onDragStart(event) {
            this.dragging = true;
            this.isClick = true;
            if (event.type === 'touchstart') {
                event.clientY = event.touches[0].clientY;
                event.clientX = event.touches[0].clientX;
            }
            this.startX = event.clientX;
        },
        onDragging(event) {
            if (this.dragging) {
                this.isClick = false;
                if (event.type === 'touchmove') {
                    event.clientY = event.touches[0].clientY;
                    event.clientX = event.touches[0].clientX;
                }
                const diff = (event.clientX - this.progressStart) / this.progressWidth;
                let newPosition = Math.floor(diff * 100);
                if (newPosition < 0) {
                    newPosition = 0;
                } else if (newPosition > 100) {
                    newPosition = 100;
                }
                this.newPosition = newPosition;
                this.setPosition(this.newPosition);
            }
        },
        onDragEnd() {
            if (this.dragging) {
                /*
         * 防止在 mouseup 后立即触发 click，导致滑块有几率产生一小段位移
         * 不使用 preventDefault 是因为 mouseup 和 click 没有注册在同一个 DOM 上
         */
                setTimeout(() => {
                    this.dragging = false;
                    if (!this.isClick) {
                        this.setPosition(this.newPosition);
                        this.$store.commit('audio/SETTING_PROGRESS', this.newPosition);
                        this.newPosition = this.activeLength;
                    }
                }, 0);
                window.removeEventListener('mousemove', this.onDragging);
                window.removeEventListener('touchmove', this.onDragging);
                window.removeEventListener('mouseup', this.onDragEnd);
                window.removeEventListener('touchend', this.onDragEnd);
                window.removeEventListener('contextmenu', this.onDragEnd);
            }
        },
        setPosition(newPosition) {
            if (newPosition === null || Number.isNaN(newPosition)) return;
            if (newPosition < 0) {
                newPosition = 0;
            } else if (newPosition > 100) {
                newPosition = 100;
            }
        },
    },
};
</script>

<style lang="less" scoped>
@import "~@/styles/animation.less";

.item-volume {
  position: relative;
}
.volume-controller {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  z-index: 758943649;
}
.audio_player-block {
  height: @player-wrapper-height;
  transition: all 0.3s;
  background-color: @player-wrapper-background;
}
.audio-player-leave-to,
.audio-player-enter {
  height: 0;
}
.audio-player-enter-to,
.audio-player-leave {
  height: @player-wrapper-height;
}

.player-bg {
  width: 100%;
  min-width: @baseWidth;
  position: fixed;
  bottom: 0;
  padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
  left: 0;
  font-size: 12px;
  user-select: none;
  box-shadow: 0 -1px 3px @player-wrapper-background;
  background-color: @player-wrapper-background;
  color: @player-wrapper-color;
  z-index: 758943649;
  transition: all 0.3s;
  &.close {
    transform: translateY(100%);
  }
}
.audio_player_show-btn {
  width: 100px;
  padding: 3px 0;
  position: absolute;
  bottom: 100%;
  right: 0;
  z-index: 1;
  text-align: center;
  background: url("~@/assets/audio_open_btn.png") no-repeat center;
  background-size: cover;
  z-index: 9;
}
.player-wrapper {
  width: 980px;
  height: @player-wrapper-height;
  margin: auto;
  padding: 10px;
  box-sizing: border-box;
  display: flex;
  justify-content: space-between;
  align-items: center;
  position: relative;

  .item-t-s:hover {
    text-shadow: 0 0 5px @player-wrapper-color;
  }

  .wrapper-controller {
    display: flex;
    padding: 0 20px;

    .item-controller-btn {
      margin: 0 5px;
      cursor: pointer;
    }
  }

  .wrapper-middle {
    width: calc(100% - 126px - 156px);
    height: 100%;
    display: flex;
    align-items: center;

    .item-audio-cover {
      width: 34px;
      height: 34px;
      min-width: 34px;
      min-height: 34px;
      margin-right: 10px;
      box-shadow: 0 0 2px darken(@player-wrapper-background, 20%);
      border-radius: 4px;
      cursor: pointer;
    }
  }

  .wrapper-audio {
    width: calc(100% - 89px - 44px);
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
  }

  .item-audio-info {
    display: flex;
    user-select: text;

    > div {
      margin-right: 10px;
      white-space: nowrap;
      cursor: pointer;
      overflow: hidden;

      &:last-child {
        margin-right: 0;
      }

      > span.active {
        position: relative;
        animation: name-move 8s 0.5s infinite linear;
      }
    }
  }

  .progress-wrapper {
    width: 100%;
    position: relative;

    .item-progress {
      height: 9px;
      border-radius: 30px;
      background-color: darken(@player-wrapper-background, 20%);
      box-shadow: 0 0 2px darken(@player-wrapper-background, 20%);
      // overflow: hidden;
    }

    .item-progress-played {
      width: 30%;
      height: 100%;
      position: absolute;
      top: 0;
      left: 0;
      z-index: 1;
      border-radius: 30px;
      background-color: @player-progress-btn;
    }

    .item-progress-loaded {
      width: 40%;
      height: 100%;
      position: absolute;
      top: 0;
      left: 0;
      z-index: 0;
      border-radius: 30px;
      background-color: lighten(@player-progress-btn, 20%);
      transition: all 3s;
    }

    .item-progress-btn {
      width: 10px;
      height: 10px;
      position: absolute;
      top: 50%;
      left: 30%;
      z-index: 2;
      transform: translateY(-50%) translateX(-50%);
      border: 3px solid #fff;
      border-radius: 50%;
      background-color: @player-progress-btn;
      box-shadow: 0 0 2px darken(@player-progress-btn, 20%);
      cursor: pointer;
    }
  }

  .wrapper-timer {
    height: 100%;
    display: flex;
    align-items: flex-end;
    padding: 0 5px;
    position: relative;
    top: 3px;
    font-size: 13px;

    > span {
      margin: 0 5px;
    }

    div:last-child {
      color: darken(@player-wrapper-color, 20%);
    }
  }

  .wrapper-controller-other {
    display: flex;
    padding-left: 20px;

    > div {
      width: 25px;
      height: 25px;
      line-height: 25px;
      margin-right: 10px;
    }

    .item-list {
      position: relative;
      display: flex;
      align-items: center;

      > span {
        display: block;
        min-width: 30px;
        height: 18px;
        line-height: 18px;
        text-align: center;
        font-size: 12px;
        font-weight: bold;
        border-radius: 0 30px 30px 0;
      }
    }
  }
}
</style>
